package edu.upenn.seas.peerreview.smui
import edu.upenn.seas.peerreview.{Id, Sink}

/* ********************************************************** */
// Coordinator

class RPCBSManager(name: String, configs : List[GameConfig], numPlayers: Int, myId:Id, t:Sink.T) extends RPCAgent[BSManagerInterface](myId, t) {
  
  def rdebug(msg: String) = Debug.debug("rpc")("[Manager] " + msg)
    
  //object that can hold one RPCThread.
  //ensures that the other is killed when one is inserted.
  //to allow for synchronization
  val threadHolder = new (RPCThread=>Unit) {
    var thread: RPCThread = null
    def apply(t: RPCThread) {
      if (thread != null) thread.kill()
      thread = t
    }
  }

  def main {

    val coordinator = new RPCProxy(Id.coordinatorId) with NameServerInterface
    coordinator.put(name, myId)

    var players : Set[Id] = Set()

    while (players.size < numPlayers) {
      respondToCall {
        case (from, 'joinServer, _) =>
          players += from
          println("=====JOINED (%d/%d): %s".format(players.size, numPlayers, from))
      }
    }

    var h_gameover: RPCThread = null
    for (game <- configs) {
      rdebug("manager: now new game has started ")
      //game now in progress
      val boardsize =  Point(game.boardSize._1, game.boardSize._2)
      val h_getconfigs =  forkhandler('getConfigs) {
        x => {
          rdebug("replied to request for getconfigs")
          Some(NewGameConfigs((players - RPCSender).toList, boardsize, game.ships))
        }
      }
  
      var numPlayerResultsReceived = 0
      while (numPlayerResultsReceived < numPlayers) {
        respondToCall {
          case (from, 'sendPlayerResult,
          (player: Id) :: (hits: Int) :: (sunks: Int) ::
          (kills: Int) :: (isWinner: Boolean) :: Nil) => {

            //HACK
            if (h_gameover != null) {h_gameover.kill(); h_gameover = null}
            
            numPlayerResultsReceived += 1
            rdebug("Number of players done so far: " + numPlayerResultsReceived)
            println("==[Manager] (%d/%d) Results for %s (%s): %d hits, %d sunks, %d kills".format(
              numPlayerResultsReceived, numPlayers,
              player, if (isWinner) "Victorious!" else "Loser.",
              hits, sunks, kills))
          }
        }
      }
    
      h_getconfigs.kill()
      h_gameover =  forkhandler('waitGameOver) { x => () } 
      rdebug("End of a single game.")
    }

    //tournament over; no configs to get
    threadHolder( forkhandler('getConfigs) {
      x => None
    })
    rdebug("Main ended.")
  }

  /*
   def handle (e: Envelope) { 
   val from = e.from
   e.contents match {  
   case LetMeLeave() =>
   if (players.contains(from)) {
   println("--- %s has abandoned the tournament", from)
   broadcast(from, players, PlayerWithdrawal(from))
   players -= from
   }
   case _ => 
   println("Coordinator: Unrecognized message")
   }
   }*/
}
